#!/bin/sh
#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
set +x
#@function: restre DB by rman.

SCRIPT_ROOT_PATH=$1
PID=$2
PARAM_NUM=$3
SCRIPTPID=$$


. "${SCRIPT_ROOT_PATH}/oracle_sbin_func.sh"
. "${SCRIPT_ROOT_PATH}/oracle_native_restore_func.sh"

#********************************define these for the functions of agent_sbin_func.sh********************************

# global var, for kill monitor
PARAM_CONTENT=`read_input_param "${PARAM_NUM}"`
test -z "$PARAM_CONTENT"              && exit_with_error "PARAM_FILE"

##############################################################
DBNAME=`get_value "${PARAM_CONTENT}" AppName`
DBINSTANCE=`get_value "${PARAM_CONTENT}" InstanceName`
DBUSER=`get_value "${PARAM_CONTENT}" UserName`
DBUSERPWD=`get_value "${PARAM_CONTENT}" Password`
ASMUSER=`get_value "${PARAM_CONTENT}" ASMUserName`
ASMUSERPWD=`get_value "${PARAM_CONTENT}" ASMPassword`
CHANNELS=`get_value "${PARAM_CONTENT}" Channel`
PIT_TIME=`get_value "${PARAM_CONTENT}" pitTime`
PIT_SCN=`get_value "${PARAM_CONTENT}" pitScn`
BACKUP=`get_value "${PARAM_CONTENT}" DataPath`
ARCHIVE=`get_value "${PARAM_CONTENT}" LogPath`
RECOVERTARGET=`get_value "${PARAM_CONTENT}" recoverTarget`
RECOVERPATH=`get_value "${PARAM_CONTENT}" recoverPath`
RECOVERORDER=`get_value "${PARAM_CONTENT}" recoverOrder`
ASMSIDNAME=`get_value "${PARAM_CONTENT}" ASMInstanceName`
ENCALGO=`get_value "${PARAM_CONTENT}" EncAlgo`
ENCKEY=`get_value "${PARAM_CONTENT}" EncKey`
PFILEPID=`get_value "${PARAM_CONTENT}" pfilePID`
RestoreBy=`get_value "${PARAM_CONTENT}" RestoreBy`
RECOVERNUM=`get_value "${PARAM_CONTENT}" recoverNum`
ORA_DB_USER=`get_value "${PARAM_CONTENT}" OracleInstallUser`
ORA_GRID_USER=`get_value "${PARAM_CONTENT}" GridInstallUser`
JOBID_LIST=`get_value "${PARAM_CONTENT}" JobIdList`
ENABLE_BCT=`get_value "${PARAM_CONTENT}" bctStatus`
ORACLE_BASE=`get_value "${PARAM_CONTENT}" AccessOracleBase`
ORACLE_HOME=`get_value "${PARAM_CONTENT}" AccessOracleHome`


test "$DBNAME" = "ERROR_PARAM_INVALID"                           && exit_with_error "DBNAME"
test "$DBINSTANCE" = "ERROR_PARAM_INVALID"                       && exit_with_error "DBINSTANCE"
test "$DBUSER" = "ERROR_PARAM_INVALID"                           && exit_with_error "DBUSER"
test "$ASMUSER" = "ERROR_PARAM_INVALID"                          && exit_with_error "ASMUSER"
test "$CHANNELS" = "ERROR_PARAM_INVALID"                         && exit_with_error "CHANNELS"
test "$PIT_TIME" = "ERROR_PARAM_INVALID"                         && exit_with_error "PIT_TIME"
test "$PIT_SCN" = "ERROR_PARAM_INVALID"                          && exit_with_error "PIT_SCN"
test "$BACKUP" = "ERROR_PARAM_INVALID"                           && exit_with_error "BACKUP"
test "$ARCHIVE" = "ERROR_PARAM_INVALID"                          && exit_with_error "ARCHIVE"
test "$METADATAPATH" = "ERROR_PARAM_INVALID"                     && exit_with_error "METADATAPATH"
test "$RECOVERTARGET" = "ERROR_PARAM_INVALID"                    && exit_with_error "RECOVERTARGET"
test "$RECOVERPATH" = "ERROR_PARAM_INVALID"                      && exit_with_error "RECOVERPATH"
test "$RECOVERORDER" = "ERROR_PARAM_INVALID"                     && exit_with_error "RECOVERORDER"
test "$ASMSIDNAME" = "ERROR_PARAM_INVALID"                       && exit_with_error "ASMSIDNAME"
test "$ENCALGO" = "ERROR_PARAM_INVALID"                          && exit_with_error "ENCALGO"
test "$PFILEPID" = "ERROR_PARAM_INVALID"                         && exit_with_error "PFILEPID"
test "$RestoreBy" = "ERROR_PARAM_INVALID"                        && exit_with_error "RestoreBy"
test "$RECOVERNUM" = "ERROR_PARAM_INVALID"                       && exit_with_error "RECOVERNUM"

BACKUP_PATH_LIST=`redirect_backup_path "${BACKUP}"`
MAIN_BACKUP_PATH=`echo "${BACKUP_PATH_LIST}" | $MYAWK -F ";" '{print $1}'`
ADDITIONAL="${MAIN_BACKUP_PATH}/additional"
BACKUP_TEMP="${MAIN_BACKUP_PATH}/tmp"

log_info "BACKUPTEMP=${BACKUP_TEMP};ADDITIONAL=$ADDITIONAL;MainBackupPath=${MAIN_BACKUP_PATH}"
test -z "${BACKUP_PATH_LIST}"                                    && exit_with_error "data path"
test -z "${MAIN_BACKUP_PATH}"                                    && exit_with_error "main data path"
test -z "$DBINSTANCE"                                            && exit_with_error "oracle instance name"
test -z "$RECOVERORDER"                                          && exit_with_error "RECOVERORDER"

if [ -n "$PIT_SCN" ] && [ "$PIT_SCN" -lt "`cat "$ADDITIONAL"/scn_dbf_max | $MYAWK '{print $1}'`" ]; then
    log_info "Base media snapshot used to restore is newer than PIT to restore $PIT_SCN."
fi

if [ -z "$PIT_TIME" ] && [ -z "$PIT_SCN" ]; then
    PIT_SCN=`cat "$ADDITIONAL"/scn_dbf_max | $MYAWK '{print $1}'`
fi

# 0 is arch resestore 1 is full restore
COPY_RESTORE=0
if [ -z "${ARCHIVE}" ]; then
    log_info "ARCHIVE is null, restore by full copy."
    COPY_RESTORE=1
fi

if [ "${RestoreBy}" -eq 1 ]; then
    log_info "Full backup, restore by copy "
    COPY_RESTORE=1
fi

if [ -n "${PIT_TIME}" ]; then
    PITTIME=`unix_timestamp_to_date "${PIT_TIME}"`
    PITTIME=$(echo "${PITTIME}" | tail -n 1)
    log_info "Convert ${PIT_TIME} to ${PITTIME}."
fi

if [ "$PIT_SCN" != "0" ]; then
    PIT="scn $PIT_SCN"
else
    PIT='time "to_date'"('$PITTIME', 'YYYY-MM-DD HH24:MI:SS')"'"'
fi

if [ -z "${CHANNELS}" ] || [ "${CHANNELS}" -eq 0 ]; then
    CHANNELS=4
    log_warn "Setting channels number to ${CHANNELS} by default"
fi

if [ "${CHANNELS}" -gt 254 ]; then
    log_error "Channels param is invalid "
    exit "${RETURN_INVALID}"
fi

IS_ENC_BK=0
if [ -n "${ENCALGO}" ] && [ -n "${ENCKEY}" ]; then
    IS_ENC_BK=1
    if [ "$ORA_PREVERSION" -gt 11 ]; then
        RMAN_ENC_SECTION="configure encryption algorithm '${ENCALGO}';"
    fi
    RMAN_ENC_SECTION="${RMAN_ENC_SECTION} set decryption identified by '${ENCKEY}';"
fi

log_info "PID=${PID};DBINSTANCE=${DBINSTANCE};DBNAME=${DBNAME};DBUSER=${DBUSER};\
ASMSIDNAME=${ASMSIDNAME};ASMUSER=${ASMUSER};DBCHANNEL=$CHANNELS;PIT_TIME=$PIT_TIME;\
PIT_SCN=$PIT_SCN;BACKUP=$BACKUP;ARCHIVE=$ARCHIVE;\
RECOVERTARGET=${RECOVERTARGET};RECOVERPATH=${RECOVERPATH};RECOVERORDER=${RECOVERORDER};\
pfilePID=${PFILEPID};RestoreBy=${RestoreBy};RECOVERNUM=$RECOVERNUM;JOBID_LIST=$JOBID_LIST;\
ORACLE_BASE=${ORACLE_BASE};ORACLE_HOME=${ORACLE_HOME}"

#********************************check host enviroment begin********************************
get_oracle_user

get_oracle_user_shell_type

env_file_list=`get_user_env_file "${ORA_DB_USER}"`
if [ $? -ne 0 ] || [ -z "$env_file_list" ]; then
    log_error "Get user env file failed"
    exit "$RETURN_INVALID"
fi

EXPORT_ORACLE_ENV=`generate_export_cmd "$env_file_list" "oracle"`
if [ $? -ne 0 ] || [ -z "$EXPORT_ORACLE_ENV" ]; then
    log_error "Get user env cmd failed"
    exit "$RETURN_INVALID"
fi

check_oracle_is_install

check_oracle_install_type

if [ "$DBISCLUSTER" -gt 0 ]; then
    get_grid_user
    get_grid_user_shell_type
    get_grid_home_path

    env_file_list=`get_user_env_file "${ORA_GRID_USER}"`
    if [ $? -ne 0 ] || [ -z "$env_file_list" ]; then
        log_error "Get user env file failed"
        exit "$RETURN_INVALID"
    fi

    EXPORT_GRID_ENV=`generate_export_cmd "$env_file_list" "grid"`
    if [ $? -ne 0 ] || [ -z "$EXPORT_GRID_ENV" ]; then
        log_error "Get user env cmd failed"
        exit "$RETURN_INVALID"
    fi
    ASMSIDNAME=`ps -ef | grep asm_...._+ | grep -v grep | ${MYAWK} -F_ '{print $NF}' | uniq`
    if [ -z "$ASMSIDNAME" ]; then
        log_error "Have no asm instance"
        exit "${RETURN_INVALID}"
    fi
fi

get_oracle_base_path

get_oracle_home_path

get_oracle_version

check_sqlplus_status

check_rman_status

get_instance_auth_type "${DBINSTANCE}"
AUTH_TYPE=$?

#********************************prepare for restore begin********************************
backup_all_version=`cat "$ADDITIONAL"/dbinfo | $MYAWK -F ";" '{print $10}'`

compare_oracle_version "$ORA_VERSION" "$backup_all_version"
UPGRADE=$?
if [ $UPGRADE -gt 2 ]; then
    log_error "Can not apply big version to low version"
    exit "$ERROR_ORACLE_VERSION_DISMATCH"
fi

INCAR_NUM=`cat "$ADDITIONAL"/dbinfo | $MYAWK -F ";" '{print $8}'`
if [ -z "${INCAR_NUM}" ]; then
    log_error "Get backup copy incranation failed."
    exit "$ERROR_SCRIPT_EXEC_FAILED"
fi

check_dg_exit

if [ "$RECOVERORDER" -eq "1" ] && [ "$DBISCLUSTER" -eq "1" ] && [ "$RECOVERTARGET" -eq "2" ]; then
    su - "${ORA_DB_USER}" "${ORACLE_SHELL_MODE}" -c "${EXPORT_ORACLE_ENV} srvctl remove database -d ${DBNAME} -f" >> "${LOG_FILE_NAME}" 2>&1
fi

if [ -n "${RECOVERPATH}" ]; then
    if [ "`rd_substr "${RECOVERPATH}" 1 1`" = "/" ]; then
        if [ ! -d "${RECOVERPATH}" ]; then
            log_error "Recover path:${RECOVERPATH} is not exist can not restore "
            exit "$ERROR_ORACLE_RECOVERPATH_NOT_EXIT"
        fi
    else
        set_env_cmd=`generate_export_grid_oracle_sid "${ASMSIDNAME}"`
        su - "${ORA_GRID_USER}" -c "${EXPORT_GRID_ENV} ${set_env_cmd} asmcmd ls ${RECOVERPATH}"
        if [ ${?} -ne 0 ]; then
            log_error "Recover path:${RECOVERPATH} is not exist can not restore "
            exit "$ERROR_ORACLE_RECOVERPATH_NOT_EXIT"
        fi
    fi
fi

log_info "Creating directories for database files"
create_dirs_from_file "$ADDITIONAL/ctrlfiles"
create_dirs_from_file "$ADDITIONAL/dataguardconffiles"
create_dirs_from_file "$ADDITIONAL/logfiles"
create_dirs_from_file "$ADDITIONAL/dbfiles"

# define params for restore
DBPW_FILE="${IN_ORACLE_HOME}/dbs/orapw${DBINSTANCE}"
PFILE_NAME="${IN_ORACLE_HOME}/dbs/ebackup-pfile${DBINSTANCE}.ora"
ENV_FILE="${STMP_PATH}/oracle_env${PID}"
RESETLOGS_ID=`cat "$ADDITIONAL"/dbinfo | $MYAWK -F ";" '{print $9}'`
TASK_TYPE=2

su - "${ORA_DB_USER}" "${ORACLE_SHELL_MODE}" -c "\cp -d -r -p ""$ADDITIONAL""/dbs ""$IN_ORACLE_HOME""" >> "${LOG_FILE_NAME}" 2>&1
log_info "rename orapw"
su - "${ORA_DB_USER}" "${ORACLE_SHELL_MODE}" -c "\cp -d -p ""${IN_ORACLE_HOME}/dbs/orapw${DBNAME} ""${IN_ORACLE_HOME}/dbs/orapw${DBINSTANCE}" >> "${LOG_FILE_NAME}" 2>&1
# delete spfile which the same instance name
delete_spfile "${DBINSTANCE}"

create_pfile_from_pm

if [ "$RECOVERTARGET" -eq 2 ]; then
    # try to replace ORACLE_HOME and ORACLE_BASE
    replace_pfile_env_by_newenv

    create_db_config_dir "$PFILE_NAME"
fi

# restore to other host
if [ "$RECOVERTARGET" -eq 2 ] || [ -n "${RECOVERPATH}" ]; then
    # modify pfile
    modify_pfile_config_param "${RECOVERPATH}"
fi

#********************************prepare for restore end********************************


#********************************restore database begin********************************
if [ "${DBISCLUSTER}" -ne 1 ] || [ "${RECOVERORDER}" -eq 1 ]; then
    # create spfile from pfile
    create_spfile_from_pfile "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}" "${RECOVERPATH}"
fi
# create init${DBINSTANCE}.ora
create_init_file "${RECOVERPATH}"

if [ ! -f "$ADDITIONAL"/livemountOK ]; then
    # only single, restart, the first node of cluster can restore file
    if [ "${DBISCLUSTER}" -ne 1 ] || [ "${RECOVERORDER}" -eq 1 ]; then
        restore_controlfile "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}" "${DBNAME}"

        log_info "Begin to exec DB restore taskType $TASK_TYPE to $PIT, ISEncBK is ${IS_ENC_BK}."

        insrestore_database_sql="${STMP_PATH}/insretore_oracle${PID}.sql"
        insrestore_database_rst="${STMP_PATH}/insretore_oracle${PID}.rst"
        get_db_role
        if [ "${DATABASE_ROLE}" != "PRIMARY" ];then
            # 如果log_file_name_convert存在才执行
            convert_dir=`cat "${PFILE_NAME}" | grep log_file_name_convert | ${MYAWK} -F"'" '{print $2}'`
            log_info "convert_dir: ${convert_dir}"
            if [ -n "$convert_dir" ]; then
                # ADG 从库新位置恢复时clear redo log,避免rename失败
                clear_redo_log_file
            fi
        fi
        if [ "$ORA_PREVERSION" -eq 11 ]; then
            if [ "${DATABASE_ROLE}" != "PRIMARY" ];then
                build_rename_log_file_for_standby "$insrestore_database_sql" "rman"
            else
                build_rename_log_file "$insrestore_database_sql"
            fi
            chown "${ORA_DB_USER}" "${insrestore_database_sql}"
            chmod 700 "${insrestore_database_sql}"
            rman_exe_script "${DBUSER}" "${DBUSERPWD}" "${insrestore_database_sql}" "${insrestore_database_rst}" "${DBINSTANCE}" -1 0
            ret_code=$?
            if [ ${ret_code} -ne 0 ];then
                log_info "Insrestore database-${DBINSTANCE} rename log file failed, ret=${ret_code}"
                delete_file "${insrestore_database_sql}" "${insrestore_database_rst}" "true"
                exit ${ret_code}
            fi
        fi

        build_db_restore_rman_script "$insrestore_database_sql"
        chown "${ORA_DB_USER}" "${insrestore_database_sql}"
        chmod 700 "${insrestore_database_sql}"

        log_info "Begin to Insrestore database."
        rman_exe_script "${DBUSER}" "${DBUSERPWD}" "${insrestore_database_sql}" "${insrestore_database_rst}" "${DBINSTANCE}" -1 1
        ret_code=$?
        if [ ${ret_code} -ne 0 ];then
            log_info "Insrestore database-${DBINSTANCE} failed, ret=${ret_code}"
            delete_file "${insrestore_database_sql}" "${insrestore_database_rst}" "true"
            exit ${ret_code}
        fi
        log_info "Insrestore database-${DBINSTANCE} succ."
        delete_file "${insrestore_database_sql}" "${insrestore_database_rst}" "true"

        if [ ${UPGRADE} -eq 1 ] && [ "${DBISCLUSTER}" -eq 1 ] && [ "${RECOVERORDER}" -eq 1 ]; then
            modify_cluster_property FALSE
            start_mount "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
        fi

        disable_database_bct "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"

        enable_bct_after_restore "${DBUSER}" "${DBUSERPWD}" "${DBINSTANCE}" "${ENABLE_BCT}"

        delete_file "${PFILE_NAME}"

        check_database_cdb_type "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}" 

        if [ ${UPGRADE} -eq 1 ] && [ "${RECOVERORDER}" -eq 1 ]; then
            oracle_upgrade "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
            if [ "${DBISCLUSTER}" -eq 1 ]; then
                modify_cluster_property TRUE
                start_open "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
            fi
        fi
        
    fi
else
    if [ "${DBISCLUSTER}" -ne 1 ] || [ "${RECOVERORDER}" -eq 1 ]; then
        move_log_file "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
    fi
fi

SPFILE_LOCATION=`cat "${IN_ORACLE_HOME}"/dbs/init"${DBINSTANCE}".ora`
if [ "${DBISCLUSTER}" -eq 1 ]; then
    # new host restore add database info and instance info to srvctl
    if [ "$RECOVERTARGET" -eq 2 ]; then
        if [ "$RECOVERORDER" -eq 1 ]; then
            SPFILE_LOCATION_NEW=`echo "${SPFILE_LOCATION}" | $MYAWK -F "=" '{print $2}'`
            su - "${ORA_DB_USER}" "${ORACLE_SHELL_MODE}" -c "${EXPORT_ORACLE_ENV} srvctl add database -d ${DBNAME} -o ${IN_ORACLE_HOME} -p ${SPFILE_LOCATION_NEW}" >> "${LOG_FILE_NAME}" 2>&1
        fi
        su - "${ORA_DB_USER}" "${ORACLE_SHELL_MODE}" -c "${EXPORT_ORACLE_ENV} srvctl add instance -d ${DBNAME} -i ${DBINSTANCE} -n `hostname`" >> "${LOG_FILE_NAME}" 2>&1
    fi
    if [ $AUTH_TYPE -eq "$INSTANCE_LOGIN_DB_TYPE" ] && [ "$RECOVERORDER" -eq 1 ]; then
        set_rac_pwd_file
    fi
    start_open "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
fi

#2. check if is CDB
check_database_cdb_type "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}" 
if [ "${ORACLE_IS_CDB}" -eq 0 ]; then
    open_all_pdbs "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"
fi

instance_status=`get_database_status "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"`
if [ $? -ne 0 ]; then
    log_error "Get instance status failed."
    exit "${RETURN_INVALID}"
fi

if [ "$instance_status" != "OPEN" ]; then
    log_error "Instance status($instance_status) no open."
    exit "${ERROR_INSTANCE_NOSTART}"
fi

if [ "${RECOVERTARGET}" -eq 2 ]; then
    grep "${DBINSTANCE}" /etc/oratab 2>> "${LOG_FILE_NAME}"
    if [ $? -ne 0 ]; then
        echo "$DBINSTANCE"":""$IN_ORACLE_HOME"":N" >> /etc/oratab
    fi
fi
log_info "Insrestore database succ"
exit 0

#********************************restore database end********************************
